package com.moliku.insurance.process.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.moliku.insurance.common.constant.CompanyEnum;
import com.moliku.insurance.common.constant.InsureStatusEnum;
import com.moliku.insurance.common.constant.OrderEnum;
import com.moliku.insurance.common.constant.PolicyConfigKeyEnum;
import com.moliku.insurance.common.response.CommonInsureResult;
import com.moliku.insurance.common.util.AXAHttpUtils;
import com.moliku.insurance.common.util.XMLUtil;
import com.moliku.insurance.model.dto.CancelInsureDTO;
import com.moliku.insurance.model.dto.DownloadInsureDTO;
import com.moliku.insurance.model.dto.insure.InsureDTO;
import com.moliku.insurance.model.dto.insure.InsuredInfoDTO;
import com.moliku.insurance.model.entity.Order;
import com.moliku.insurance.model.entity.OrderDetail;
import com.moliku.insurance.model.entity.axa.*;
import com.moliku.insurance.process.mapper.BaseOrderMapper;
import com.moliku.insurance.process.service.ConfigService;
import com.moliku.insurance.process.strategy.PolicyStrategy;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 安盛保险
 *
 * @author Mr.Liu
 * @since 2021/2/5
 */
@Slf4j
@Service("AxaService")
@AllArgsConstructor
public class AxaServiceImpl implements PolicyStrategy {
    /**
     * 安盛成功状态
     */
    private static final String SUCCESS_STATUS = "0";
    /**
     * 重复投保状态
     */
    private static final String REDO_SUBMIT = "101";
    /**
     * 成功
     */
    private static final String SUCCES_STATUS_CODE = "0000";
    /**
     * 安盛返回的成功状态
     */
    private static final String RESPONSE_STATUS = "status";
    /**
     * 安盛返回的成功
     */
    private static final String RESPONSE_STATUS_CODE = "statusCode";

    private final BaseOrderMapper baseOrderMapper;

    private final ConfigService configService;


    @Override
    public CommonInsureResult submitPolicy(InsureDTO request) {
        Order order = baseOrderMapper.selectById(request.getLocalOrderId());
        if (null == order) {
            log.info("安盛投保失败,未查询到该订单:{}", request.getLocalOrderId());
            return CommonInsureResult.submitPolicyFail(InsureStatusEnum.INSURE_FAIL_5102);
        }
        //密钥等信息
        String username = configService.getConfigValue(CompanyEnum.AXA, PolicyConfigKeyEnum.USERNAME);
        String password = configService.getConfigValue(CompanyEnum.AXA, PolicyConfigKeyEnum.PASSWORD);
        String submitUrl = configService.getConfigValue(CompanyEnum.AXA, PolicyConfigKeyEnum.SUBMIT_POLICY_URL);
        //拼装参数
        String xmlStr = getXmlStr(request);
        //发起调用
        String resultStr = AXAHttpUtils.synPdmData(xmlStr, username, password, submitUrl);
        log.info("安盛投保返回:{}", resultStr);
        //保存返回结果
        OrderDetail orderDetail = baseOrderMapper.selectDeatailByOrderId(order.getId());
        orderDetail.setInsureRsp(resultStr);
        baseOrderMapper.updateOrderDeatailByOrderId(orderDetail);

        cn.hutool.json.JSONObject object = JSONUtil.xmlToJson(resultStr);
        //xmll转为jsonn
        log.info("转换json格式:{}", object);
        //判断状态
        if (SUCCESS_STATUS.equals(object.getStr(RESPONSE_STATUS)) && SUCCES_STATUS_CODE.equals(object.getStr(RESPONSE_STATUS_CODE))) {
            log.info("安盛投保成功:{}", object.getStr("policyNo"));
            order.setStatus(OrderEnum.CLOSED_NO_REFUND.getValue());
            order.setPolicyNo(object.getStr("policyNo"));
            order.setUrl(object.getStr("elPolicyAddress"));
            baseOrderMapper.updateById(order);
            log.info("投保成功!");
            return CommonInsureResult.submitPolicySuccess(object.getStr("policyNo"));
        }
        if (REDO_SUBMIT.equals(object.getStr(RESPONSE_STATUS))) {
            log.info("安盛重复投保:{}", object.getStr("applyPolicyNo"));
            // TODO
            return CommonInsureResult.submitPolicyFail(InsureStatusEnum.INSURE_FAIL_5101);
        }
        log.info("安盛投保失败:{}", object.getJSONObject("TXTpaic").getJSONObject("TXTpaicResponse").getStr("message"));

        return CommonInsureResult.submitPolicyFail(object.getJSONObject("TXTpaic").getJSONObject("TXTpaicResponse").getStr("message"));
    }

    @Override
    public CommonInsureResult cancelPolicy(CancelInsureDTO request) {
        //密钥等信息
        String username = configService.getConfigValue(CompanyEnum.AXA, PolicyConfigKeyEnum.USERNAME);
        String password = configService.getConfigValue(CompanyEnum.AXA, PolicyConfigKeyEnum.PASSWORD);
        String submitUrl = configService.getConfigValue(CompanyEnum.AXA, PolicyConfigKeyEnum.SUBMIT_POLICY_URL);

        Order order = baseOrderMapper.selectByPolicyNoAndCompany(request.getPolicyNo(), CompanyEnum.AXA.getCode());
        AxaPolicy policy = new AxaPolicy();
        //险种
//        policy.setPlanCode(request.getTerminalNo());
        //产品编码
        policy.setProductCode(order.getProduct());
        policy.setPolicyNo(request.getPolicyNo());
        //总信息
        AxaTXTpaicRequest axaTxtPaicRequest = new AxaTXTpaicRequest();
        axaTxtPaicRequest.setPolicy(policy);
        //交易时间
        axaTxtPaicRequest.setTransExeDate(DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
        axaTxtPaicRequest.setTransRefId(order.getSerialNo());
//        交易类型 002注销保单
        axaTxtPaicRequest.setTransType("002");
        //xml根节点
        AxaTxtPaic axaTxtPaic = new AxaTxtPaic();
        axaTxtPaic.setTxTpaicRequest(axaTxtPaicRequest);
        String xmlStr = XMLUtil.converToXml(axaTxtPaic, "gb2312");
        //发起调用
        String resultStr = AXAHttpUtils.synPdmData(xmlStr, username, password, submitUrl);
        log.info("安盛退保返回:{}", resultStr);
        //保存返回结果
        OrderDetail orderDetail = baseOrderMapper.selectDeatailByOrderId(order.getId());
        orderDetail.setCancelPolicyRsp(resultStr);
        baseOrderMapper.updateOrderDeatailByOrderId(orderDetail);
        //解析
        cn.hutool.json.JSONObject object = JSONUtil.xmlToJson(resultStr);
        if (SUCCESS_STATUS.equals(object.getStr(RESPONSE_STATUS)) && SUCCES_STATUS_CODE.equals(object.getStr(RESPONSE_STATUS_CODE))) {
            log.info("安盛退保成功:{}", object.getStr("policyNo"));
        }
        log.info("安盛退保失败:{}", object.getJSONObject("TXTpaic").getJSONObject("TXTpaicResponse").getStr("message"));
        return CommonInsureResult.cancelPolicyFail();
    }

    @Override
    public CommonInsureResult downloadPolicy(DownloadInsureDTO downloadInsure) {
        return CommonInsureResult.downloadPolicyFail();
    }

    private String getXmlStr(InsureDTO request) {
        //密钥等信息
        String agentCode = configService.getConfigValue(CompanyEnum.AXA, PolicyConfigKeyEnum.AGENCY_USERID);
        //保单基本信息
        AxaPersonalLine personalLine = new AxaPersonalLine();
        personalLine.setFurthestCity(request.getOrder().getDestination());
        //投保人信息
        AxaParty party = new AxaParty();
        //投保人类型  1个人 2组织
        party.setPartyTypeCode("1");
        // 角色类型 002 投保人
        party.setRoleTypeCode("002");
        party.setFullName(request.getPolicyHolder().getcName());
        party.setGender("0".equals(request.getPolicyHolder().getSex()) ? "2" : "1");
        party.setBirthDate(request.getPolicyHolder().getBirthDay());
        party.setCertiType(AxaParty.map.get(request.getPolicyHolder().getCardType()));
        party.setCertiNo(request.getPolicyHolder().getCardNo());
        party.setEmail(request.getPolicyHolder().getEmail());
        party.setPersPhone(request.getPolicyHolder().getMobile());
        //被保人信息
        AxaParty party1 = new AxaParty();
        List<InsuredInfoDTO> insureds = request.getInsureds();
        for (InsuredInfoDTO insured : insureds) {
            //被保人类型 1个人 2组织
            party1.setPartyTypeCode("1");
            //类型 001 被保人
            party1.setRoleTypeCode("001");
            party1.setFullName(insured.getCName());
            party1.setGender("0".equals(request.getPolicyHolder().getSex()) ? "2" : "1");
            party1.setBirthDate(insured.getBirthDay());
            party1.setCertiType(AxaParty.map.get(insured.getCardType()));
            party1.setCertiNo(insured.getCardNo());
            party1.setEmail(insured.getEmail());
            party1.setPersPhone(insured.getMobile());
            //与投保人关系
            party1.setRelApplicant("1");
        }
        //保单信息
        AxaPolicy policy = new AxaPolicy();
        //险种
//        policy.setPaymentMode(request.getPolicyHolder().getPayMth());
        policy.setPlanCode("889");
        policy.setProductCode(request.getOrder().getProductCode());
        //数量 默认为1
        policy.setCount("1");
        //申请时间
        policy.setTransApplDate(DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
        //起保时间
        policy.setTransBeginDate(request.getOrder().getStartTime());
        //终保时间
        policy.setTransEndDate(request.getOrder().getEndTime());
        policy.setAgentCode(agentCode);
        //币种
        policy.setCurrencyCode("01");
        policy.setTotalActualPremium(String.valueOf(request.getOrder().getPremium()));
        policy.setTotalStandardPremium(String.valueOf(request.getOrder().getPremium()));
        //被保险人信息
        List<AxaParty> partyArrayList = new ArrayList<>();
        //投保人
        partyArrayList.add(party);
        //被保人
        partyArrayList.add(party1);
        policy.setParty(partyArrayList);
        //投保信息
        policy.setPersonalLine(personalLine);
        //总信息
        AxaTXTpaicRequest axaTxtAicRequest = new AxaTXTpaicRequest();
        axaTxtAicRequest.setPolicy(policy);
        //交易时间
        axaTxtAicRequest.setTransExeDate(DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss"));
        axaTxtAicRequest.setTransRefId(request.getOrder().getSerialNumber());
        // 交易类型 001 投保
        axaTxtAicRequest.setTransType("001");
        //xml根节点
        AxaTxtPaic axaTxtPaic = new AxaTxtPaic();
        axaTxtPaic.setTxTpaicRequest(axaTxtAicRequest);
        String xmlStr = XMLUtil.converToXml(axaTxtPaic, "gb2312");
        return xmlStr;
    }
}
